package org.example.spring.simple.framework.context.support;

import org.example.spring.simple.framework.beans.config.ZBeanDefinition;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * BeanDefinitionReader主要完成对application.properties配 置文件的解析工作，
 * 通过构造方法获取从 ApplicationContext传过来的locations配置文件路径，然后解析，
 * 扫描并保存所有相关的类并提供统一的访问入口。
 */
public class ZBeanDefinitionReader {
    //获取配置文件中的key
    private final String SCAN_PACKAGE = "scanPackage";

    private List<String> registryBeanClasses = new ArrayList<>();
    private Properties config = new Properties();

    public ZBeanDefinitionReader(String... locations) {
        //通过URL找到文件
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:", ""));
        try {
            config.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        doScanner(config.getProperty(SCAN_PACKAGE));
    }

    private void doScanner(String scanPackage) {
        //URL转换为路径
        URL url = this.getClass().getClassLoader().getResource("/"
                + scanPackage.replaceAll("\\.", "/"));
        File classPath = new File(url.getFile());
        for (File file : classPath.listFiles()) {
            if (file.isDirectory()) {
                doScanner(scanPackage + "." + file.getName());
            } else {
                if (!file.getName().endsWith(".class")) {
                    continue;
                }
                String className = (scanPackage + "." + file.getName().replace(".class", ""));
                registryBeanClasses.add(className);
            }
        }
    }

    public Properties getConfig() {
        return this.config;
    }

    /**
     * 把配置文件中扫描到的所有配置信息转换为BeanDefinition对象，一遍之后的IoC操作
     * @return
     */
    public List<ZBeanDefinition> loadBeanDefinitions() {
        List<ZBeanDefinition> result = new ArrayList<>();
        try {
            for (String className : registryBeanClasses) {
                Class<?> beanClass = Class.forName(className);
                if (beanClass.isInterface()) {
                    continue;
                }
                result.add(doCreateBeanDefinition(toLowerFirstCase(beanClass.getSimpleName()), beanClass.getName()));
                Class<?>[] interfaces = beanClass.getInterfaces();
                for (Class<?> i : interfaces) {
                    result.add(doCreateBeanDefinition(i.getName(), beanClass.getName()));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 把配置信息转换为BeanDefinition
     * @param factoryBeanName
     * @param beanClassName
     * @return
     */
    private ZBeanDefinition doCreateBeanDefinition(String factoryBeanName, String beanClassName) {
        ZBeanDefinition beanDefinition = new ZBeanDefinition();
        beanDefinition.setBeanClass(beanClassName);
        beanDefinition.setFactoryBeanName(factoryBeanName);
        return beanDefinition;
    }

    private String toLowerFirstCase(String name) {
        char[] chars = name.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }
}
